/************************************************************************
 * @file AbstractService.cpp
 * @author Ian Chen
 * @version 1.0
 *
 * @section LICENSE
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 3 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
 * General Public License for more details at
 * http://www.gnu.org/licenses/lgpl.html
 *
 ************************************************************************/
#include <QtConcurrent/QtConcurrent>

#include <plugin/service/AbstractService.h>

namespace antu
{
namespace plugin
{
AbstractService::AbstractService()
{
}

bool AbstractService::registerCommand(AbstractCommandSharedPtr &command)
{
    if (command == nullptr)
        return false;

    if (this->m_oRegisteredCommands.find(command->commandName()) ==
            this->m_oRegisteredCommands.end())
    {
        return false;
    }

    this->m_oRegisteredCommands.insert(pair<QString, AbstractCommandSharedPtr>(command->commandName(), command));
    return true;
}

AbstractCommand::CommandReturnType AbstractService::execute(const QString &commandName, const CommandParameters &inputs, CommandParameters &outputs)
{
    AbstractCommandSharedPtr command = this->findCommand(commandName);

    if (command == nullptr)
        return AbstractCommand::CommandNotFound;
    AbstractCommand::CommandReturnType returnType = command->execute(this->m_oCommandContext, inputs, outputs);

    if (returnType == AbstractCommand::ParametersValidationFailure)
    {
        outputs.insert(pair<QString, QVariant>("usage", QVariant(command->usage())));
    }
    return returnType;
}

AbstractCommand::CommandReturnType AbstractService::execute(const QString &parameters, CommandParameters &outputs)
{
    int index = parameters.indexOf(' ');
    if (index >= 0)
    {
        QString commandName = parameters.mid(0, index).trimmed();
        QString line = parameters.mid(index).trimmed();
        AbstractCommandSharedPtr command = this->findCommand(commandName);

        if (command == nullptr)
        {
            return AbstractCommand::CommandNotFound;
        }
        else
        {
            CommandParameters inputs;
            if (command->parseInputs(line, inputs))
                return command->execute(this->m_oCommandContext, inputs, outputs);
            else
            {
                outputs.insert(pair<QString, QVariant>("usage", QVariant(command->usage())));
                return AbstractCommand::ParametersValidationFailure;
            }
        }
    }
    else
    {
        return AbstractCommand::CommandLineUnrecognized;
    }
}

AbstractCommandSharedPtr AbstractService::findCommand(const QString &commandName) const
{
    map<QString, AbstractCommandSharedPtr>::const_iterator iter = this->m_oRegisteredCommands.find(commandName);

    if (iter != this->m_oRegisteredCommands.end())
    {
        return iter->second;
    }
    return AbstractCommandSharedPtr();
}

}
}
